<script setup lang="ts">
import CommentPop from '@/views/detail/components/CommentPop.vue'
import detailApi from '@/service/api/detail'
import followApi from '@/service/api/follow'
import logApi from '@/service/api/log'
import { getColor } from '@/enum/color'

function IsPhone() {
  var info = navigator.userAgent
  return /mobile/i.test(info)
}
const imgScroll = ref<HTMLDivElement | null>(null)
const isMoile = ref(IsPhone())
const route = useRoute()
const router = useRouter()
const state: any = reactive({
  id: '',
  currenImg: '',
  pageBg: '',
  showTool: true,
  isOpenComment: false,
  tableData: []
})
const closeComment = () => {
  if (!isMoile.value && width.value <= 1550) {
    state.isOpenComment = false
  }
}
const chapterState: any = reactive({
  curren: -1,
  list: []
})
const getZjImg = async (image_id?: number) => {
  const { data } = await detailApi.menuImg({
    menu_id: chapterState.list[chapterState.curren].id
  })
  const newWidht = isMoile.value ? 310 : 800
  let totalHeight = 0
  state.tableData = data.map((el, index) => {
    const oldWidth = 750
    const oldHeight = Number(el.height)
    const newHeight = (oldHeight / oldWidth) * newWidht
    el.height = Math.round(newHeight)
    totalHeight += newHeight
    el.totalHeight = totalHeight
    el.show = index < 5
    return el
  })
  if (!image_id) {
    imgScroll.value?.scrollTo({
      top: 0
    })
  } else {
    if (imgScroll.value) {
      nextTick(() => {
        const info = state.tableData.find(el => el.id === image_id)
        imgScroll.value?.scrollTo({
          top: info.totalHeight
        })
      })
    }
  }

  if (state.tableData > 0) {
    state.currenImg = state.tableData[0]
    state.pageBg = state.tableData[0].image_url
  }
}
const getMenu = async () => {
  const { data } = await detailApi.menu({
    photo_id: state.id
  })
  chapterState.list = data
  if (data.length > 0) {
    chapterState.curren = 0
    logApi
      .getInfo({
        photo_id: state.id
      })
      .then(res => {
        if (res.data?.id) {
          chapterState.curren = chapterState.list.findIndex(
            el => el.id === res.data.menu_id
          )
          getZjImg(res.data.image_id)
        } else {
          getZjImg()
        }
      })
      .catch(() => {
        getZjImg()
      })
  } else {
    msgUtil.$message.error('暂无章节')
  }
}
let logTimer: any = null
const addLog = () => {
  if (logTimer) {
    clearTimeout(logTimer)
    logTimer = null
  }
  logTimer = setTimeout(() => {
    const params: any = {
      photo_id: state.id,
      menu_id: chapterState.list[chapterState.curren].id
    }
    if (state.currenImg?.id) {
      params.image_id = state.currenImg.id
    }
    logApi.add(params)
  }, 550)
}
const handNext = () => {
  if (chapterState.curren === chapterState.list.length - 1) {
    msgUtil.$message.error('已经是最后一章了')
    return
  }
  chapterChange(chapterState.curren + 1)
}
const handPre = () => {
  if (chapterState.curren === 0) {
    msgUtil.$message.error('已经是第一章了')
    return
  }
  chapterChange(chapterState.curren - 1)
}
const chapterChange = async (index: number) => {
  chapterState.curren = index
  await getZjImg()
  addLog()
}
const init = () => {
  getMenu()
  getDetail()
}
// 目录
const handMenu = () => {
  if (chapterState.list.length === 0) {
    msgUtil.$message.error('暂无目录')
    return
  }
  handComeent(4)
}
const info = ref<any>({
  tags: [],
  commentCount: 0,
  coll_count: 0,
  view: 0
})
const replyInfo = ref<any>({})
const getReplyUser = async () => {
  if (info.value.releaseid) {
    const { data } = await detailApi.replyUser(info.value.releaseid)
    replyInfo.value = data
  }
}
const getDetail = async () => {
  const { data } = await detailApi.detail(state.id)
  data.tags = data.tags.map(el => {
    const info = getColor()
    return {
      name: el,
      ...info
    }
  })
  info.value = data
  getReplyUser()
}
const handFollow = async () => {
  if (replyInfo.value.is_follow) {
    await followApi.cancel({
      userid: replyInfo.value.id
    })
    replyInfo.value.is_follow = false
  } else {
    await followApi.add({
      userid: replyInfo.value.id
    })
    replyInfo.value.is_follow = true
  }
}
const { width } = useWindowSize()
const commentRef = ref()

const handComeent = (current?: number) => {
  if (!isMoile.value && width.value <= 1550) {
    state.isOpenComment = true
  }
  if (info.value.id) {
    commentRef.value.open(toRaw(info.value), toRaw(state.currenImg), current)
  }
}

const checkChange = (e: any) => {
  router.replace({
    query: {
      id: e.id
    }
  })
  state.id = e.id
  init()
}

// 页面滚动
let lastScrollTop = 0
let showTime: any = null
const scrollState: any = reactive({
  isBottom: false,
  isTop: true,
  touchStartY: 0,
  touchEndY: 0,
  timer: null
})

const cleatScrollTimer = () => {
  if (scrollState.timer) {
    clearTimeout(scrollState.timer)
    scrollState.timer = null
  }
}
const onScroll = e => {
  if (!e) return
  const target = e.target as HTMLDivElement
  const scrollTop = target.scrollTop
  const scrollHeight = target.scrollHeight
  const clientHeight = target.clientHeight
  if (showTime) {
    clearTimeout(showTime)
    showTime = null
  }

  if (scrollTop === 0) {
    // 到达顶部
    scrollState.isBottom = false
    if (scrollState.isTop) {
      return
    }
    cleatScrollTimer()
    scrollState.timer = setTimeout(() => {
      scrollState.isTop = true
    }, 200)
  } else if (scrollTop + clientHeight >= scrollHeight) {
    // 到达底部
    scrollState.isTop = false
    if (scrollState.isBottom) {
      return
    }
    cleatScrollTimer()
    scrollState.timer = setTimeout(() => {
      scrollState.isBottom = true
    }, 200)
  } else {
    scrollState.isBottom = false
    scrollState.isTop = false
    cleatScrollTimer()
  }
  state.showTool = scrollTop <= lastScrollTop
  lastScrollTop = scrollTop <= 0 ? 0 : scrollTop // For Mobile or negative scrolling
}
const showTool = () => {
  state.showTool = !state.showTool
}
let timer: any = null
const showImgChange = (scrollTop: number) => {
  clearTimeout(timer)
  timer = null
  const index = state.tableData.findIndex(el => el.totalHeight > scrollTop)
  const minIndex = index - 8
  const maxIndex = index + 8
  state.tableData.forEach((el, index) => {
    if (index >= minIndex && index <= maxIndex) {
      el.show = true
    }
  })
}
const scrollChange = () => {
  if (!imgScroll.value) return
  const scrollTop = imgScroll.value.scrollTop
  const images = imgScroll.value.querySelectorAll('img')
  let currentIndex = 0
  let minDistance = Infinity
  if (timer) {
    clearTimeout(timer)
  }
  timer = setTimeout(() => {
    showImgChange(scrollTop)
  }, 220)

  images.forEach((img, index) => {
    const imgTop = img.offsetTop
    const distance = Math.abs(imgTop - scrollTop)
    if (distance < minDistance) {
      minDistance = distance
      currentIndex = index
    }
  })
  const newCurrenImg = state.tableData[currentIndex]
  if (state.currenImg.id !== newCurrenImg.id) {
    state.currenImg = newCurrenImg
    addLog()
  }
}

const handleKeyDown = event => {
  if (event.shiftKey && event.key === 'D') {
    handNext()
  } else if (event.shiftKey && event.key === 'A') {
    handPre()
  } else if (event.shiftKey && event.key === 'W') {
    handMenu()
  }
}

const onTouchStart = (e: TouchEvent) => {
  if (scrollState.isBottom || scrollState.isTop) {
    scrollState.touchStartY = e.touches[0].clientY
  } else {
    scrollState.touchStartY = 0
  }
}

const onTouchMove = (e: TouchEvent) => {
  scrollState.touchEndY = e.touches[0].clientY
}

const onTouchEnd = () => {
  if (scrollState.touchStartY === 0) return
  if (
    scrollState.isBottom &&
    scrollState.touchStartY - scrollState.touchEndY > 70
  ) {
    handNext()
  }
  // if (
  //   scrollState.isTop &&
  //   scrollState.touchStartY - scrollState.touchEndY < -70
  // ) {
  //   handPre()
  // }
}

onMounted(() => {
  if (imgScroll.value) {
    imgScroll.value.addEventListener('scroll', onScroll)
    imgScroll.value.addEventListener('touchstart', onTouchStart)
    imgScroll.value.addEventListener('touchmove', onTouchMove)
    imgScroll.value.addEventListener('touchend', onTouchEnd)
  }
  window.addEventListener('keydown', handleKeyDown)
  const id = route.query.id as string
  state.id = id
  init()
})

onBeforeUnmount(() => {
  if (imgScroll.value) {
    imgScroll.value.removeEventListener('scroll', onScroll)
    imgScroll.value.removeEventListener('touchstart', onTouchStart)
    imgScroll.value.removeEventListener('touchmove', onTouchMove)
    imgScroll.value.removeEventListener('touchend', onTouchEnd)
  }
  window.removeEventListener('keydown', handleKeyDown)
})
</script>
<template>
  <div
    class="mh-detail-page"
    ref="detailRef"
    :class="{ 'mh-detail-page-open': state.isOpenComment }"
  >
    <div class="mh-detail-page-bg">
      <img :src="state.pageBg" alt="" />
      <div class="mask"></div>
    </div>
    <div
      class="mh-detail-page-main"
      ref="imgScroll"
      @click="showTool"
      @scroll="scrollChange"
    >
      <div
        class="img-w"
        v-for="item in state.tableData"
        :key="item.id"
        :data-id="item.id"
      >
        <template v-if="item.show">
          <img
            :style="{ height: item.height + 'px' }"
            v-lazydm="item.image_url"
          />
        </template>
        <template v-else>
          <div class="img-placeholder" :style="{ height: item.height + 'px' }">
            <common-loading />
          </div>
        </template>
      </div>
    </div>
    <Transition name="slide-fade">
      <div class="menu-tool" v-show="state.showTool">
        <div class="pre" @click="handPre">
          <i class="esayIcon esayIcon-gengduo"></i>
        </div>
        <div class="tool" @click="handMenu">
          <span>目录</span>
        </div>
        <div class="next" @click="handNext">
          <i class="esayIcon esayIcon-gengduo"></i>
        </div>
      </div>
    </Transition>

    <comment-pop
      :replyInfo="replyInfo"
      :chapterIndex="chapterState.curren"
      :chapterList="chapterState.list"
      ref="commentRef"
      @close="closeComment"
      @check="checkChange"
      @follow="handFollow"
      @change="chapterChange"
    />
  </div>
</template>
<style scoped lang="scss">
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.mh-detail-page {
  height: 100%;
  background-color: #212121;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-y: scroll;
  transition: padding-right 0.3s;

  &-open {
    padding-right: 300px;
  }

  &-bg {
    z-index: 0;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    overflow: hidden;

    img {
      filter: blur(60px);
      opacity: 0.8;
      width: 100%;
      height: 100%;
      user-select: none;
      transform: scale(1.2);
    }

    .mask {
      z-index: -1;
      background-color: #000;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }
  }

  &-main {
    flex: 1 0 0;
    width: 800px;
    margin: 0 auto;
    background-color: #212121;
    overflow: auto;
    position: relative;

    .img-w {
      margin-top: -1px;
      width: 100%;
      overflow: hidden;
      img {
        width: 100%;
        display: block;
      }
    }

    .charper-menu {
      display: none;
    }
  }

  .menu-tool {
    position: fixed;
    z-index: 9;
    right: calc(50vw - 400px - 100px);
    transition: right 0.3s;
    bottom: 80px;
    display: flex;
    align-items: center;
    background-color: rgba(255, 255, 255, 0.8);
    border-radius: 15px;
    &-open {
      right: calc(50vw - 400px - 60px + 150px);
    }
    .pre {
      width: 30px;
      display: flex;
      justify-content: center;
      transform: rotate(180deg);
      cursor: pointer;
      i {
        font-size: 15px;
      }
    }
    .tool {
      cursor: pointer;
    }
    .next {
      width: 30px;
      display: flex;
      justify-content: center;
      cursor: pointer;
    }
  }
}

@media (max-width: 800px) {
  .mh-detail-page {
    .menu-tool {
      background-color: rgba(255, 255, 255, 0.8);
      right: 20px;
      bottom: 20px;
    }
    &-main {
      width: 310px;
    }
    .bottom {
      width: 310px;
    }
  }
}
</style>
<style lang="scss">
.slide-fade-enter-active {
  transition: all 0.3s ease-out;
}

.slide-fade-leave-active {
  transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-fade-enter-from,
.slide-fade-leave-to {
  transform: translateX(20px);
  opacity: 0;
}

.img-placeholder {
  background-color: #000;
  position: relative;
  width: 100%;
  display: flex;
  justify-content: center;
  padding-top: 30px;
}
</style>
